package org.tigris.atlas.web.wlw;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.tigris.atlas.factory.FactoryFactory;
import org.tigris.atlas.service.EntityServiceResponse;
import org.tigris.atlas.transfer.AbstractTransferObjectFactoryInterface;
import org.tigris.atlas.transfer.TransferObject;
import org.tigris.atlas.util.CalendarUtils;
import org.tigris.atlas.web.struts.InputForm;

import org.apache.beehive.netui.pageflow.Forward;

/**
 * Base controller class for entity maintenance portlets
 *
 * @author sandrews
 *
 */
public abstract class EntityMaintenancePageFlowController extends AbstractPageFlowController {

	private TransferObject currentEntity;
	private TransferObject previousEntity;
	private String returnAction;
	
	public Forward begin() {
		loadEntity();
		return determineForward();
	}

	public final String getCurrentUserName() {
		String username = getRequest().getRemoteUser();
		if (StringUtils.isBlank(username)) {
			throw new IllegalStateException("Not logged in");
		}
		return username;
	}

	private EntityServiceResponse loadEntityAndPopulateForm(InputForm form) {
		EntityServiceResponse response = loadEntity();
		populateForm( form );
		return response;
	}

	protected abstract void populateForm(InputForm form);

	protected abstract void populateEntity(InputForm form);

	protected final EntityServiceResponse loadEntity() {
		EntityServiceResponse response = lookupEntity();
		currentEntity = response.getEntity();
		return response;
	}
	
	protected abstract EntityServiceResponse lookupEntity();

	public Forward newAction(InputForm form) {
		newActionSetup();
		populateForm( form );
        return determineForward();
	}

	public Forward newAction() {
		newActionSetup();
        return determineForward();
	}
	
	private void newActionSetup() {
		
		if (currentEntity == null) {
			currentEntity = createNewTOInstance();
			setupNewEntity();
		}
		
		previousEntity = currentEntity;
		returnAction = getRequest().getParameter("returnAction");
		currentEntity = createNewTOInstance();
		setupNewEntity();
	}
	
	protected final TransferObject createNewTOInstance() {
		AbstractTransferObjectFactoryInterface factory =
			(AbstractTransferObjectFactoryInterface) FactoryFactory.createFactory(FactoryFactory.TRANSFER_OBJECT, getTransferObjectClass());
		
		return factory.createTransferObject(getEntityName());
	}
	
	protected abstract Class getTransferObjectClass();

	protected abstract void setupNewEntity();

	public Forward confirmDeleteAction(InputForm form) {
		EntityServiceResponse response = loadEntityAndPopulateForm( form );
		returnAction = getRequest().getParameter("returnAction");
		handleMessages( response );
		return determineForward();
	}

	public Forward deleteAction(InputForm form) {
		EntityServiceResponse response = deleteEntity();
		currentEntity = response.getEntity();
		handleMessages( response );
		return determineForward();
	}

	protected abstract EntityServiceResponse deleteEntity();

	public Forward editAction(InputForm form) {
		EntityServiceResponse response = loadEntityAndPopulateForm(form);
		returnAction = getRequest().getParameter("returnAction");
		handleMessages(response);
		return determineForward();
	}

	public Forward saveAction(InputForm form) {
		populateEntity(form);
        EntityServiceResponse response = saveEntity();
        setCurrentEntity(response.getEntity());
        handleMessages( response, form );
        return determineForward();
	}

	protected abstract EntityServiceResponse saveEntity();

	public Forward viewAction(InputForm form) {
		EntityServiceResponse response = loadEntityAndPopulateForm(form);
		handleMessages( response );
		return determineForward();
	}

	protected final TransferObject getCurrentEntity() {
		return currentEntity;
	}

	protected final void setCurrentEntity(TransferObject entity) {
		currentEntity = entity;
	}
	
	protected abstract String getEntityName();

	public Forward printerFriendlyDetailAction(InputForm form) {        
		populateForm( form );
        return determineForward();
	}
	
	public Forward returnToViewAction(InputForm form) {        
		populateForm(form);
        return determineForward();
	}
	
	public Forward returnFromDeleteAction() {        
        return new Forward(returnAction);
	}
	
	public Forward returnFromEditAction(InputForm form) {  
        return new Forward(returnAction);
	}
	
	public Forward returnFromAddAction(InputForm form) {    
		currentEntity = previousEntity;
		return new Forward(returnAction);
	}

    public Map getMonthOptions() {
    	return CalendarUtils.getMonths();
    }

    public Map getDayOptions() {
    	return CalendarUtils.getDays();
    }

    public Map getHourOptions() {
    	return CalendarUtils.getHours();
    }

    public Map getMinuteOptions() {
        return CalendarUtils.getMinutes();
    }

    public List getYearOptions() {
    	return CalendarUtils.getYears();
    }
	
	public List getFutureYearOptions() {
    	return CalendarUtils.getFutureYears();
    }
    
    public int getYearListStartValue() {
    	return getFirstYear();
    }
    	    
    public int getYearListEndValue() {
    	return Integer.parseInt(CalendarUtils.getCurrentYear());
    }

    protected int getFirstYear() {
    	return CalendarUtils.getFirstYear();
    }
    
    public boolean isEditMode() {
    	// If the id of the entity is populated, we're editing
    	return getCurrentEntity().getKey().getValue() != null;
    }

    /**
     * Subclass responsibility to get the current user profile id
     *
     * @return Long The user profile id
     */
    protected abstract Long getCurrentUserId();
    
    public Forward reset(InputForm form) {
		if (isEditMode()) {
            loadEntityAndPopulateForm(form);
        } else {
            form.reset(getMapping(), getRequest());
        }
        
		return determineForward();
	}

}
